﻿using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace CGF
{
    [AddComponentMenu("CGFramework/CButton")]
    public class CButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerClickHandler
    {
        public enum Transition
        {
            None,
            Scale,
            Color,
            Sprite,
            Texture
        }

        public static Action buttonCommonSoundAction;
        public Text text;
        public float triggerInterval = 1;
        public bool globalSound = true;

        public RectTransform rectTransform
        {
            get { return transform as RectTransform; }
        }

        public Action onPress, onRelease, onClick, onDoubleClick, onLongPress;
        private float canPressTime, canReleaseTime, canClickTime, canDoubleClickTime, doubleClickTime;
        private int currPointerId = -1;

        //点击变换效果
        public Transition transition = Transition.Scale;
        public MaskableGraphic transTarget;
        public float pressScale = 0.98f;
        public Color pressColor = new Color(0.95f, 0.95f, 0.95f, 1);
        public Sprite pressSprite;
        public Texture2D pressTexture;
        public bool useNativeSize;

        private Color colorDefault;
        private Sprite defaultSprite;
        private Texture defaultTexture;
        private Vector3 defaultScale;
        private Vector2 touchPos;
        private Canvas canvas;
        private Camera uiCamera;
        private float pressTime;

        void Awake()
        {
            //点击变换效果
            if (!transTarget)
            {
                transTarget = GetComponent<MaskableGraphic>();
            }

            if (transTarget)
            {
                if (transTarget is Image)
                {
                    defaultSprite = (transTarget as Image).sprite;
                }
                else if (transTarget is RawImage)
                {
                    defaultTexture = (transTarget as RawImage).texture;
                }

                colorDefault = transTarget.color;
            }
        }

        void OnEnable()
        {
            canPressTime = 0;
            canReleaseTime = 0;
            canClickTime = 0;
            canDoubleClickTime = 0;
        }

        void Start()
        {
            CanvasScaler canvasScaler = rectTransform.GetComponentInParent<CanvasScaler>();
            canvas = canvasScaler.GetComponent<Canvas>();
            if (canvas && canvas.renderMode != RenderMode.ScreenSpaceOverlay)
            {
                uiCamera = canvas.worldCamera;
            }
        }

        private void Update()
        {
            if (pressTime > 0 && pressTime < Time.time)
            {
                pressTime = 0;
                onLongPress?.Invoke();
            }
        }

        public void OnPointerDown(PointerEventData eventData)
        {
            if (enabled)
            {
                touchPos = ScreenToUGUIPoint(eventData.position);
                if (canPressTime < Time.time)
                {
                    pressTime = Time.time + 1;
                    
                    if (onPress != null)
                    {
                        onPress.Invoke();
                    }

                    if (globalSound) buttonCommonSoundAction?.Invoke();

                    //点击变换效果
                    if (transTarget)
                    {
                        switch (transition)
                        {
                            case Transition.Scale:
                                if (defaultScale == Vector3.zero)
                                {
                                    defaultScale = transTarget.transform.localScale;
                                }

                                transTarget.transform.localScale = defaultScale * pressScale;
                                break;
                            case Transition.Color:
                                transTarget.color = pressColor;
                                break;
                            case Transition.Sprite:
                                if (pressSprite)
                                {
                                    (transTarget as Image).sprite = pressSprite;
                                    if (useNativeSize) transTarget.SetNativeSize();
                                }

                                break;
                            case Transition.Texture:
                                if (pressTexture)
                                {
                                    (transTarget as RawImage).texture = pressTexture;
                                    if (useNativeSize) transTarget.SetNativeSize();
                                }

                                break;
                        }
                    }
                }

                currPointerId = eventData.pointerId;
            }
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            bool canExecUp = true;
            if (Application.isMobilePlatform)
            {
                canExecUp = (currPointerId == eventData.pointerId);
            }

            if (canExecUp)
            {
                if (canReleaseTime < Time.time)
                {
                    if (onRelease != null)
                    {
                        onRelease.Invoke();
                    }
                    canReleaseTime = Time.time + triggerInterval;
                }

                currPointerId = -1;

                //变换效果恢复
                TransResume();
                
                if (canPressTime < Time.time)
                {
                    canPressTime = Time.time + triggerInterval;
                }
            }
        }

        private void TransResume()
        {
            if (transTarget)
            {
                switch (transition)
                {
                    case Transition.Scale:
                        if (defaultScale != Vector3.zero) transTarget.transform.localScale = defaultScale;
                        break;
                    case Transition.Color:
                        if (colorDefault != new Color(0, 0, 0, 0)) transTarget.color = colorDefault;
                        break;
                    case Transition.Sprite:
                        if (defaultSprite)
                        {
                            (transTarget as Image).sprite = defaultSprite;
                            if (useNativeSize) transTarget.SetNativeSize();
                        }

                        break;
                    case Transition.Texture:
                        if (defaultTexture)
                        {
                            (transTarget as RawImage).texture = defaultTexture;
                            if (useNativeSize) transTarget.SetNativeSize();
                        }

                        break;
                }
            }
        }

        private Vector2 ScreenToUGUIPoint(Vector2 screenPos)
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, screenPos, uiCamera, out Vector2 uiPos);
            return uiPos;
        }

        public void OnPointerClick(PointerEventData eventData)
        {
            if (enabled)
            {
                if (onClick != null && canClickTime < Time.time)
                {
                    Vector2 pos = ScreenToUGUIPoint(eventData.position);
                    if (Vector2.Distance(pos, touchPos) < 50)
                    {
                        onClick.Invoke();
                        canClickTime = Time.time + triggerInterval;
                    }
                }

                if (doubleClickTime > Time.time)
                {
                    doubleClickTime = 0;
                    if (canDoubleClickTime < Time.time)
                    {
                        onDoubleClick?.Invoke();
                        canDoubleClickTime = Time.time + triggerInterval;
                    }
                }
                else
                {
                    doubleClickTime = Time.time + 0.5f;
                }
            }
        }

        public void SetPress(Action action)
        {
            onPress = action;
        }
        
        public void SetLongPress(Action action)
        {
            onLongPress = action;
        }

        public void RemovePress()
        {
            onPress = null;
            TransResume();
        }

        public void SetRelease(Action action)
        {
            onRelease = action;
        }

        public void RemoveUp()
        {
            onRelease = null;
            TransResume();
        }

        public void SetClick(Action action)
        {
            onClick = action;
        }

        public void RemoveClick()
        {
            onClick = null;
            TransResume();
        }

        public void SetDoubleClick(Action action)
        {
            onDoubleClick = action;
        }

        public void RemoveDoubleClick()
        {
            onDoubleClick = null;
            TransResume();
        }

        public void ClearAllEvents()
        {
            onClick = null;
            onPress = null;
            onRelease = null;
            onDoubleClick = null;
            TransResume();
        }

        /// <summary>
        /// 外部改变缩放值后重设这里的缩放值
        /// </summary>
        public void SetDefaultScale(Vector3 sacle)
        {
            defaultScale = sacle;
        }

#if UNITY_EDITOR
        [UnityEditor.MenuItem("CGFramework/创建 CButton")]
        [UnityEditor.MenuItem("GameObject/CGFramework/创建 CButton", priority = -2200)]
        static void Create()
        {
            GameObject go = new GameObject("Btn");
            go.layer = LayerMask.NameToLayer("UI");
            go.transform.SetParent(UnityEditor.Selection.activeGameObject.transform, false);
            go.AddComponent<Image>();
            go.AddComponent<CButton>();
            UnityEditor.EditorUtility.SetDirty(go);
        }
#endif
    }
}